#include <imbus.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define NO_TEST_OBJECT_MAIN
#include "test_object.h"
#include "test_object.c"

#include "im_internals.h"

static const IMChar *test_server_address = "local:/tmp/im-test-server";

IMBool on_receive_callback (IMMainLoop *loop, IMInt watch_id, IMPointer data)
{
    IMPointer obj;
    IMInt timeout = -1;
    IMInt ret;
    IMIOError error = IM_IO_ERROR_NONE;
    IMConnection *connection = IM_CONNECTION (data);
    IMIOChannel *out = im_io_channel_unix_new (1);
    IMStream *stream = im_text_stream_new ();
    _im_assert (connection);

    fprintf (stderr, "Receive data from watch id = %d\n", watch_id);

    while ((ret = im_connection_pending (connection, &error)) > 0) {
        obj = im_connection_next (connection, &timeout, &error);

        if (obj) {
            im_stream_put_object (stream, obj);
            im_stream_write (stream, out, &timeout, &error);
            if (im_object_get_type (obj) == IM_TYPE_STRING &&
                im_string_compare_str (IM_STRING(obj), "quit") == 0) {
                printf ("Quit main loop.\n");
                im_main_loop_quit (loop);
            }
            im_object_unref (obj);
        } else {
            ret = -1;
            break;
        }
    }

    im_object_unref (out);
    im_object_unref (stream);

    if (ret < 0) {
        fprintf (stderr, "Error occurred while reading from watch id = %d, error = %d\n",
                 watch_id, error);
        return FALSE;
    }
    return TRUE;
}

void on_new_connection_handler (IMServer *server, IMIOChannel *io_channel,
                                IMPointer data)
{
    IMMainLoop *main_loop = im_server_get_main_loop (server);
    IMConnection *connection = im_connection_new (io_channel);
    IMInt watch_id;

    watch_id = im_main_loop_add_io_read_watch (main_loop,
                                               io_channel,
                                               on_receive_callback,
                                               connection,
                                               im_object_unref);

    printf ("New IO read watch was added for fd: %d, watch id: %d\n",
            im_io_channel_unix_get_fd (io_channel),
            watch_id);
}

int main (int argc, char *argv [])
{
    IMMainLoop *loop;
    IMServer *server;
    IMIOError error;

    im_init (&argc, &argv);

    (void) TYPE_POINT;
    (void) TYPE_CIRCLE;

#if IM_ENABLE_DEBUG
    _im_slice_print_debug_info();
#endif

    loop = im_main_loop_unix_new ();
    server = im_server_new (IM_TYPE_SERVER_UNIX);
    if (!im_server_listen (server, test_server_address, &error)) {
        fprintf (stderr, "Failed to listen to %s.\n",
                 test_server_address);
        return 1;
    }
    im_server_set_main_loop (server, loop);
    im_server_set_new_connection_handler (server,
                                          on_new_connection_handler,
                                          0, 0);

    im_main_loop_run (loop);
    im_object_unref (loop);
    im_object_unref (server);

#if IM_ENABLE_DEBUG
    _im_slice_print_debug_info();
#endif
}
/*
vi:ts=4:nowrap:ai:expandtab
*/
